package com.liang.manage.auth.facade.server.iml;

import com.liang.bbs.common.constant.RedisConstants;
import com.liang.manage.auth.facade.dto.project.ProjectDTO;
import com.liang.manage.auth.facade.entity.ProjectPo;
import com.liang.manage.auth.facade.entity.ProjectPoExample;
import com.liang.manage.auth.facade.mapper.ProjectPoMapper;
import com.liang.manage.auth.facade.mapstruct.ProjectMS;
import com.liang.manage.auth.facade.server.ProjectService;
import com.liang.manage.auth.facade.server.UserService;

import com.liang.nansheng.common.auth.UserSsoDTO;
import com.liang.nansheng.common.enums.ResponseCode;
import com.liang.nansheng.common.web.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.util.List;

/**
 * @author 王华安
 * @date 2021-04-21 20:32
 */
@Slf4j
@Component
@Service
public class ProjectServiceImpl implements ProjectService {
    @Autowired
    private ProjectPoMapper projectPoMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 项目（系统）信息初始化
     */
    @PostConstruct
    private void init() {
        ProjectPoExample example = new ProjectPoExample();
        example.createCriteria().andIsDeletedEqualTo(false);
        // 获取所有项目（系统）信息
        List<ProjectPo> projectPos = projectPoMapper.selectByExample(example);
        projectPos.forEach(projectPo -> {
            redisTemplate.opsForHash().put(RedisConstants.PROJECT_ID_TO_NAME_KEY, String.valueOf(projectPo.getId()), projectPo.getName());
        });
    }

    /**
     * 新增系统
     *
     * @param projectDTO
     * @param currentUser
     * @return
     */
    @Override
    public Boolean create(ProjectDTO projectDTO, UserSsoDTO currentUser) {
        if (StringUtils.isBlank(projectDTO.getName()) || StringUtils.isBlank(projectDTO.getDesc())) {
            throw BusinessException.build(ResponseCode.NOT_EXISTS, "参数不合规");
        }
        if (isNameExist(null, projectDTO.getName())) {
            throw BusinessException.build(ResponseCode.NAME_EXIST, "系统名重复");
        }
        projectDTO.setState(true);
        projectDTO.setIsDeleted(false);
        projectDTO.setCreateUser(currentUser.getUserId());
        projectDTO.setUpdateUser(currentUser.getUserId());
        LocalDateTime now = LocalDateTime.now();
        projectDTO.setCreateTime(now);
        projectDTO.setUpdateTime(now);
        ProjectPo projectPo = ProjectMS.INSTANCE.toPo(projectDTO);
        if (projectPoMapper.insertSelective(projectPo) <= 0) {
            throw BusinessException.build(ResponseCode.OPERATE_FAIL, "新增系统失败");
        }
        // 更新项目（系统）的id、name对
        redisTemplate.opsForHash().put(RedisConstants.PROJECT_ID_TO_NAME_KEY, String.valueOf(projectPo.getId()), projectPo.getName());

        return true;
    }

    /**
     * 获取系统
     *
     * @param projectDTO
     * @return
     */
    @Override
    public List<ProjectDTO> getList(ProjectDTO projectDTO) {
        ProjectPoExample example = new ProjectPoExample();
        ProjectPoExample.Criteria criteria = example.createCriteria().andIsDeletedEqualTo(false);
        if (StringUtils.isNotBlank(projectDTO.getName())) {
            criteria.andNameLike("%" + projectDTO.getName() + "%");
        }
        if (projectDTO.getState() != null) {
            criteria.andStateEqualTo(projectDTO.getState());
        }

        List<ProjectDTO> projectDTOS = ProjectMS.INSTANCE.toDTO(projectPoMapper.selectByExample(example));
        // 通过id获取name
        projectDTOS.forEach(dto -> {
            dto.setCreateUserName(userService.getNameByIdFromRedis(dto.getCreateUser()));
            dto.setUpdateUserName(userService.getNameByIdFromRedis(dto.getUpdateUser()));
        });

        return projectDTOS;
    }

    /**
     * 删除系统
     *
     * @param id
     * @param currentUser
     * @return
     */
    @Override
    public Boolean delete(Integer id, UserSsoDTO currentUser) {
        ProjectPo projectPo = new ProjectPo();
        projectPo.setId(id);
        projectPo.setIsDeleted(true);
        projectPo.setUpdateUser(currentUser.getUserId());
        projectPo.setUpdateTime(LocalDateTime.now());
        if (projectPoMapper.updateByPrimaryKeySelective(projectPo) <= 0) {
            throw BusinessException.build(ResponseCode.OPERATE_FAIL, "删除失败");
        }
        // 删除项目（系统）的id、name对
        redisTemplate.opsForHash().delete(RedisConstants.PROJECT_ID_TO_NAME_KEY, String.valueOf(projectPo.getId()));

        return true;
    }

    /**
     * 更新系统
     *
     * @param projectDTO
     * @param currentUser
     * @return
     */
    @Override
    public Boolean update(ProjectDTO projectDTO, UserSsoDTO currentUser) {
        if (StringUtils.isBlank(projectDTO.getName()) || StringUtils.isBlank(projectDTO.getDesc())) {
            throw BusinessException.build(ResponseCode.NOT_EXISTS, "参数不合规");
        }
        if (isNameExist(projectDTO.getId(), projectDTO.getName())) {
            throw BusinessException.build(ResponseCode.NAME_EXIST, "系统名称重复");
        }
        projectDTO.setState(null);
        projectDTO.setIsDeleted(null);
        projectDTO.setCreateUser(null);
        projectDTO.setCreateTime(null);
        projectDTO.setUpdateUser(currentUser.getUserId());
        projectDTO.setUpdateTime(LocalDateTime.now());
        ProjectPo projectPo = ProjectMS.INSTANCE.toPo(projectDTO);
        if (projectPoMapper.updateByPrimaryKeySelective(projectPo) <= 0) {
            throw BusinessException.build(ResponseCode.OPERATE_FAIL, "更新系统失败");
        }
        if (StringUtils.isNotBlank(projectPo.getName())) {
            // 更新项目（系统）的id、name对
            redisTemplate.opsForHash().put(RedisConstants.PROJECT_ID_TO_NAME_KEY, String.valueOf(projectPo.getId()), projectPo.getName());
        }

        return true;
    }

    /**
     * 通过系统id获取系统
     *
     * @param projectId
     * @return
     */
    @Override
    public ProjectDTO getById(Integer projectId) {
        return ProjectMS.INSTANCE.toDTO(projectPoMapper.selectByPrimaryKey(projectId));
    }

    /**
     * 从Redis按项目ID获取项目名称
     *
     * @param projectId
     * @return
     */
    @Override
    public String getNameByIdFromRedis(Integer projectId) {
        Object projectName = redisTemplate.opsForHash().get(RedisConstants.PROJECT_ID_TO_NAME_KEY, String.valueOf(projectId));
        return String.valueOf(projectName);
    }

    /**
     * 判断系统名称是否已经存在
     *
     * @param projectId 系统id
     * @param name      系统名称
     * @return
     */
    private boolean isNameExist(Integer projectId, String name) {
        ProjectPoExample example = new ProjectPoExample();
        example.createCriteria().andIsDeletedEqualTo(false)
                .andNameEqualTo(name);
        List<ProjectPo> projectPos = projectPoMapper.selectByExample(example);
        if (projectPos.size() > 1) {
            return true;
        } else if (projectPos.size() == 1) {
            // 更新时projectId是有值的
            return !projectPos.get(0).getId().equals(projectId);
        }
        return false;
    }

}
